// Copyright (c) XiGuan 2023
// Author： xiguan
// Email: xiguan.teng@qq.com
// Create on 2023/11/14
// TODO:
//

#ifndef WEBSERVER_TIMER_HEAPTIMER_H
#define WEBSERVER_TIMER_HEAPTIMER_H

#include <Log.h>
#include <time.h>

#include <chrono>
#include <functional>
#include <unordered_map>

typedef std::function<void()> TimeoutCallBack;
typedef std::chrono::high_resolution_clock Clock;  // 高精时间
typedef std::chrono::milliseconds MS;
typedef Clock::time_point TimeStamp;

struct TimerNode {
  int id;
  TimeStamp expires;
  TimeoutCallBack timeout_callback;

  bool operator<(const TimerNode &t) { return this->expires < t.expires; }
};

class HeapTimer {
 private:
  /**
   * @brief 删除指定index下的结点
   * @param idx
   */
  void del_(size_t idx);

  /**
   * @brief 向上调整堆
   * @param idx
   */
  void sift_up_(size_t idx);

  /**
   * @brief     向下调整堆
   * @param idx 指定位置
   * @param n   堆的大小
   * @return    返回是否有做过调整
   */
  bool sift_down_(size_t idx, size_t n);

  /**
   * @brief 交换两个结点数据
   * @param idx
   * @param jdx
   */
  void swap_node_(size_t idx, size_t jdx);

  std::vector<TimerNode> heap_; // 小根堆 依据时间戳

  std::unordered_map<int, size_t> ref_; // ID->idx的哈希

 public:
  HeapTimer();

  ~HeapTimer();

  void adjust(int id, int new_expires);

  /**
   * @brief 添加结点进堆
   * @param id
   * @param timeout
   * @param timeout_callback
   */
  void add(int id, int timeout, const TimeoutCallBack &timeout_callback);

  /**
   * @brief 对指定id的结点进行回调
   * @param id
   */
  void do_work(int id);

  /**
   * @brief 清除堆中所有元素
   */
  void clear();

  /**
   * @brief 清除超时结点，并调用超时函数
   */
  void tick();

  /**
   * @brief 弹出堆顶元素
   */
  void pop();

  int get_next_tick();
};

#endif  // WEBSERVER_TIMER_HEAPTIMER_H
